#pragma once 

#include <boost/asio.hpp>

#include "GameServer.h"
#include "GameClient.h"
#include "state/State.h"

using boost::asio::ip::tcp;

class GameManager;
class tcp_server;
class GameClient;
class ComImpl;

class Communicator
{
public:
    Communicator(bool isServer);
	~Communicator();
    /* Assure we are in sync with all other gameclients */
    virtual void update(float dt, State::Type type);

    /* enable filling the inBuffer from a socket */
    std::vector<unsigned char>& getInBuffer() { return inBuffer; }

	static boost::asio::io_service& getIoService();

protected:

	ComImpl* impl;

    std::vector<unsigned char> outBuffer;
    std::vector<unsigned char> inBuffer;
};



namespace Packets {

    enum PacketType { GAME_PENDING_PACKET, PLAYER_STATE_PACKET, OBJ_STATE_PACKET, WELCOME_PACKET };

struct GamePendingPacket
{
    enum Msg { NONE, READY };

	GamePendingPacket() : 
		msg(NONE)
	{}

    GamePendingPacket(Msg msg) : 
        msg(msg)
    {}

    Msg msg;
};

/* Header for state being received from another gameclient */
struct PlayerStatePacket
{
    PlayerStatePacket(int playerId) 
        : playerId(playerId), type(PLAYER_STATE_PACKET)
    {}
    PlayerStatePacket() 
        : playerId(-1), type(PLAYER_STATE_PACKET)
    {}

    int playerId;
    PacketType type;
};

struct WelcomePacket
{
    WelcomePacket(int id) :
        id(id), type(WELCOME_PACKET)
    {}
    WelcomePacket() : 
        id(-1), type(WELCOME_PACKET)
    {}

    int id;
    PacketType type;
};

struct GameInfoPacket
{
	GameInfoPacket(int numbPlayers) : 
		numbPlayers(numbPlayers)
	{}
	GameInfoPacket() : 
		numbPlayers(-1)
	{}

	int numbPlayers;
};

struct PlayerStartInfo
{
	enum startArea { start_north, start_south, start_west, start_east };

	PlayerStartInfo(int id, startArea startPos, int pos, int color) : 
		id(id), startPos(startPos), pos(pos), color(color)
	{}
	PlayerStartInfo() : 
		id (-1), startPos(start_north), pos(0), color(0xffffff00)
	{}

	int id;
	startArea startPos;
	int pos;
	int color;
};

#if 0 
/* header for every object being received */
struct ObjStatePacket
{
	ObjStatePacket(Serializable::Type objType, bool sent, int id) 
		: objType(objType), known(sent), id(id), type(OBJ_STATE_PACKET)
	{}
	ObjStatePacket() 
		: objType(Serializable::null_type), known(false), id(-1), type(OBJ_STATE_PACKET)
	{}

	Serializable::Type  objType;
	bool                known;
	int                 id;
	PacketType type;
};
#endif

} // namespace Packets 